/**
 * 索引类型指的不是某一个特定的类型工具，
 * 它其实包含三个部分：索引签名类型、索引类型查询 与 索引类型访问，这三者都是独立的类型工具。
 * 唯一共同点是，它们都通过索引的形式来进行类型操作，
 * 其中，索引签名类型 是声明，
 * 索引类型查询 与 索引类型访问 两者则是读取。
*/

/**
 * 索引签名类型
 * 索引签名类型主要指的是在 接口 或 类型别名 中，通过以下语法来快速声明一个 键值类型一致 的类型结构：
*/
interface AllStringTypes {
    [key: string]: string;
}

type AllStringTypesA = {
    [key: string]: string;
}
//这意味着在实现这个 类型结构 的变量中只能声明 字符串类型的键
//但由于 JavaScript 中，对于 obj[prop] 形式的访问会将 数字索引访问 转换为 字符串索引访问
//因此，在 字符串索引签名类型 中仍然可以声明 数字类型的键。类似的，symbol 类型也是如此
const foo: AllStringTypes = {
    "hanxuming": "599",
    599: "hanxuming",
    [Symbol("ddd")]: 'symbol',
}

//索引签名类型 也可以和 具体的键值对 类型声明并存，但这时这些 具体的键值类型 也需要符合 索引签名类型 的声明：
interface StringOrBooleanTypes {
    propA: number;
    propB: boolean;
    [key: string]: number | boolean;
}
//否则会报错：
interface StringOrBooleanTypesA {
    propA: number;
    propB: boolean;
    [key: string]: number;
}

//索引签名类型的一个常见场景：是在重构 JavaScript 代码时，
//为内部属性较多的对象声明一个 any 的索引签名类型，
//以此来暂时支持对类型未明确属性的访问，并在后续一点点补全类型：
interface AnyTypeHere {
    [key: string]: any;
}
const fooA: AnyTypeHere['hanxuming'] = 'any value';

//export {}：解决“无法重新声明块范围变量”错误提示问题
export { }